﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIT.Controls.Containers;
using UIT.Controls;

namespace UIT
{
    public class ControlCollectionWrapper<TParent, TChild> : DisposableObservableCollectionWrapper<IContainer, IControl, TParent, TChild>
        where TParent : IContainer
        where TChild : IControl, IContainable<TParent>
    {
        public ControlCollectionWrapper(IDisposableObservableCollection<TParent, TChild> innerList)
            : base(innerList)
        {

        }
    }

    public class DisposableObservableCollectionWrapper<TParent, TChild, TRealParent, TRealChild> : IDisposableObservableCollection<TParent, TChild>
        where TParent : IContainer<TParent, TChild>
        where TChild : IContainable<TParent>, IDisposable
        where TRealParent : TParent
        where TRealChild : TChild, IContainable<TRealParent>, IDisposable
    {
        public DisposableObservableCollectionWrapper(IDisposableObservableCollection<TRealParent, TRealChild> innerList)
        {
            this.innerList = innerList;
            innerList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(innerList_CollectionChanged);
        }

        void innerList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (CollectionChanged != null)
                CollectionChanged(this, e);
        }

        #region ICollection<TChild> Members

        public void Add(TChild item)
        {
            innerList.Add((TRealChild)item);
        }

        public void Clear()
        {
            ((ICollection<TChild>)innerList).Clear();
        }

        public bool Contains(TChild item)
        {
            return innerList.Contains((TRealChild)item);
        }

        public void CopyTo(TChild[] array, int arrayIndex)
        {
            TRealChild[] realArray = new TRealChild[array.Length];
            innerList.CopyTo(realArray, 0);
            for (int i = arrayIndex; i < array.Length; i++)
                array[i] = realArray[i - arrayIndex];
        }

        public int Count
        {
            get { return ((ICollection<TChild>)innerList).Count; }
        }

        public bool IsReadOnly
        {
            get { return ((ICollection<TChild>)innerList).IsReadOnly; }
        }

        public bool Remove(TChild item)
        {
            return innerList.Remove((TRealChild)item);
        }

        #endregion

        #region IEnumerable<TChild> Members

        public IEnumerator<TChild> GetEnumerator()
        {
            return (IEnumerator<TChild>)innerList.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return innerList.GetEnumerator();
        }

        #endregion

        #region INotifyCollectionChanged Members

        public event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            innerList.CollectionChanged -= innerList_CollectionChanged;
            innerList.Dispose();
            innerList = null;
        }

        #endregion

        private IDisposableObservableCollection<TRealParent, TRealChild> innerList;

        #region IDisposableObservableCollection<TParent,TChild> Members

        public int IndexOf(TChild control)
        {
            return innerList.IndexOf((TRealChild)control);
        }

        #endregion

        public int Add(object value)
        {
            return innerList.Add(value);
        }

        public bool Contains(object value)
        {
            return innerList.Contains(value);
        }

        public int IndexOf(object value)
        {
            return innerList.IndexOf(value);
        }

        public void Insert(int index, object value)
        {
            innerList.Insert(index, value);
        }

        public bool IsFixedSize
        {
            get { return innerList.IsFixedSize; }
        }

        public void Remove(object value)
        {
            innerList.Remove(value);
        }

        public void RemoveAt(int index)
        {
            innerList.RemoveAt(index);
        }

        public object this[int index]
        {
            get
            {
                return innerList[index];
            }
            set
            {
                innerList[index] = value;
            }
        }

        public void CopyTo(Array array, int index)
        {
            innerList.CopyTo(array, index);
        }

        public bool IsSynchronized
        {
            get { return innerList.IsSynchronized; }
        }

        public object SyncRoot
        {
            get { return innerList.SyncRoot; }
        }
    }
}
